package demo.mina.util;

/**
 *
 */
public class BitOperator {

    /** DIGITAL */
    public static final String DIGITAL = "0123456789ABCDEF";

    /**
     * 把byte[]转化位整形,通常为指令用
     *
     * @param value value
     * @return int int
     * @throws Exception
     * @since 2022.1.1
     */
    public static int byteToInteger(byte[] value) {
        int result;
        if (value.length == 1) {
            result = oneByteToInteger(value[0]);
        } else if (value.length == 2) {
            result = twoBytesToInteger(value);
        } else if (value.length == 3) {
            result = threeBytesToInteger(value);
        } else if (value.length == 4) {
            result = fourBytesToInteger(value);
        } else {
            result = fourBytesToInteger(value);
        }
        return result;
    }

    /**
     * 把一个byte转化位整形,通常为指令用
     *
     * @param value value
     * @return int int
     * @throws Exception
     * @since 2022.1.1
     */
    private static int oneByteToInteger(byte value) {
        return (int) value & 0xFF;
    }

    /**
     * 把一个2位的数组转化位整形
     *
     * @param value value
     * @return int int
     * @throws Exception
     * @since 2022.1.1
     */
    private static int twoBytesToInteger(byte[] value) {
        int temp0 = value[0] & 0xFF;
        int temp1 = value[1] & 0xFF;
        return ((temp0 << 8) + temp1);
    }

    /**
     * 把一个3位的数组转化位整形
     *
     * @param value value
     * @return int int
     * @throws Exception
     * @since 2022.1.1
     */
    private static int threeBytesToInteger(byte[] value) {
        int temp0 = value[0] & 0xFF;
        int temp1 = value[1] & 0xFF;
        int temp2 = value[2] & 0xFF;
        return ((temp0 << 16) + (temp1 << 8) + temp2);
    }

    /**
     * 把一个4位的数组转化位整形,通常为指令用
     *
     * @param value value
     * @return int int
     * @throws Exception
     * @since 2022.1.1
     */
    private static int fourBytesToInteger(byte[] value) {
        int temp0 = value[0] & 0xFF;
        int temp1 = value[1] & 0xFF;
        int temp2 = value[2] & 0xFF;
        int temp3 = value[3] & 0xFF;
        return ((temp0 << 24) + (temp1 << 16) + (temp2 << 8) + temp3);
    }

    /**
     * Gets check sum 4 jt 808 *
     *
     * @param bs    bs
     * @param start start
     * @param end   end
     * @return the check sum 4 jt 808
     * @since 2022.1.1
     */
    public static byte getCheckSum4JT808(byte[] bs, int start, int end) {
        if (start < 0 || end > bs.length) {
            throw new ArrayIndexOutOfBoundsException("getCheckSum4JT808 error : index out of bounds(start=" + start
                                                     + ",end=" + end + ",bytes length=" + bs.length + ")");
        }
        byte cs = 0;
        for (int i = start; i < end; i++) {
            cs ^= bs[i];
        }
        return cs;
    }

    /**
     * BCD字节数组===>String
     *
     * @param bytes bytes
     * @return 十进制字符串 string
     * @since 2022.1.1
     */
    public static String bcd2String(byte[] bytes) {
        StringBuilder temp = new StringBuilder(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            // 高四位
            temp.append((bytes[i] & 0xf0) >>> 4);
            // 低四位
            temp.append(bytes[i] & 0x0f);
        }
        //忽略0开头
        return temp.substring(0, 1).equalsIgnoreCase("0") ? temp.substring(1) : temp.toString();
    }

    /**
     * 截取数组指定返回的数据，将其转换为int类型
     *
     * @param data       data
     * @param startIndex start index
     * @param length     length
     * @return int int
     * @since 2022.1.1
     */
    public static int parseIntFromBytes(byte[] data, int startIndex, int length) {
        // 字节数大于4,从起始索引开始向后处理4个字节,其余超出部分丢弃
        final int len = Math.min(length, 4);
        byte[] tmp = new byte[len];
        System.arraycopy(data, startIndex, tmp, 0, len);
        return byteToInteger(tmp);
    }

    /**
     * byte数组转换成16进制字符串
     *
     * @param src src
     * @return string string
     * @since 2022.1.1
     */
    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    /**
     * 将int转换为 16进制数据
     *
     * @param data    data
     * @param byteNum byte num
     * @return the string
     * @since 2022.1.1
     */
    public static String intToHexString(int data, int byteNum) {
        StringBuilder sb = new StringBuilder();
        for (int m = 0; m < byteNum; m++) {
            sb.append("00");
        }
        int totalLen = byteNum * 2;
        String tmp = Integer.toHexString(data);
        sb.replace(totalLen - tmp.length(), totalLen, tmp);
        return sb.toString();
    }

    /**
     * string转换为字节数组
     *
     * @param hex hex
     * @return byte [ ]
     * @since 1.0
     */
    public static byte[] stringToBytes(String hex) {
        String hex1 = hex.replace(" ", "");
        char[] hex2char = hex1.toCharArray();
        byte[] bytes = new byte[hex1.length() / 2];
        byte temp;
        for (int p = 0; p < bytes.length; p++) {
            temp = (byte) (DIGITAL.indexOf(hex2char[2 * p]) * 16);
            temp += DIGITAL.indexOf(hex2char[2 * p + 1]);
            bytes[p] = (byte) (temp & 0xff);
        }
        return bytes;
    }

    /**
     * 截取指定范围
     *
     * @param data   data
     * @param start  start
     * @param length length
     * @return byte [ ]
     * @since 1.0
     */
    public static byte[] rangeBytes(byte[] data, int start, int length) {
        byte[] bytes = new byte[length];
        System.arraycopy(data, start, bytes, 0, length);
        return bytes;
    }

    /**
     * Bin 2 hex
     *
     * @param input input
     * @return the string
     * @since 1.0
     */
    public static String bin2hex(String input) {
        StringBuilder sb = new StringBuilder("0x");
        //长度不足4位的补0
        input = supplementZero(input);
        int len = input.length();
        System.out.println("原数据长度：" + (len / 8) + "字节");
        for (int i = 0; i < len / 4; i++){
            //每4个二进制位转换为1个十六进制位
            String temp = input.substring(i * 4, (i + 1) * 4);
            int tempInt = Integer.parseInt(temp, 2);
            String tempHex = Integer.toHexString(tempInt).toUpperCase();
            sb.append(tempHex);
        }
        return sb.toString();
    }

    /**
     * Supplement zero
     *
     * @param str str
     * @return the string
     * @since 1.0
     */
    private static String supplementZero(String str) {
        StringBuilder builder = new StringBuilder();
        int length = str.length();
        while (length % 4 != 0) {
            builder.append(0);
            length++;
        }
        return builder.append(str).toString();
    }
}
